/*
 * Copyright (C) 2010-2012 Enrique Lara (enrique.posix2.lara@gmail.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package app.transitalarm;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;

import android.content.ContentUris;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;

import android.database.Cursor;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;

import android.net.Uri;

import android.os.Bundle;

import android.view.ContextMenu;

import android.view.ContextMenu.ContextMenuInfo;

import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;

import android.view.View.OnClickListener;

import android.view.ViewGroup;

import android.widget.AdapterView;

import android.widget.AdapterView.OnItemClickListener;

import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.ListView;

import app.transitalarm.model.Alarm;
import app.transitalarm.model.App;

import app.transitalarm.provider.Projections;
import app.transitalarm.provider.Tables.Alarms;

import app.transitalarm.util.Constants;
import app.transitalarm.util.Log;

import trs.wmata.BusAgency;
import trs.wmata.TrainAgency;

import java.util.ArrayList;

/*
 * XXX Allow for selection and matching of multiple headsigns/destinations.
 * XXX add Refresh and Done to StopViewer.
 * XXX add Help for alarm edit screen.
 *
 * XXX TimeToGo - move match count into "title"
 *
 * XXX dashboard similar to Clock with Time/Date and Weather with link to weather widget + warnings + map
 *
 * XXX Add preference for default "action" in AllAlarms (view, edit, run).
 * 
 * XXX find nearby station.
 */
public class AllAlarms extends Activity implements OnItemClickListener {
    private static final String TAG = "AllAlarms";
    public static final int MENU_ITEM_EDIT = Menu.FIRST;
    public static final int MENU_ITEM_DELETE = Menu.FIRST + 1;
    public static final int MENU_ITEM_START_NOW = Menu.FIRST + 2;
    public static final int MENU_ITEM_INSERT = Menu.FIRST + 3;
    public static final int MENU_ITEM_SETTING = Menu.FIRST + 4;
    public static final int MENU_ITEM_VIEW = Menu.FIRST + 5;
    private static final int MENU_ITEM_ENABLE = Menu.FIRST + 6;
    private static final int MENU_ITEM_DISABLE = Menu.FIRST + 7;
    private static final int MENU_ITEM_ABOUT = Menu.FIRST + 8;
    private ListView allAllarms = null;
    private LayoutInflater layoutInflater;
    private Bitmap enabledClockBmp;
    private Bitmap enabledIndicatorBmp;
    ProgressDialog loadingDialog = null;

    private class AlarmAdapter extends BaseAdapter {
        private final ArrayList<Alarm> alarms;

        public AlarmAdapter(final Context context, final Cursor c) {
            alarms = App.loadAllAlarms(c, context, Projections.AlarmsAll.AGENCY_ID);
        }

        @Override
        public int getCount() {
            return alarms.size();
        }

        @Override
        public long getItemId(final int position) {
            return getAlarm(position).getId();
        }

        @Override
        public Object getItem(final int position) {
            return getAlarm(position);
        }

        private Alarm getAlarm(final int position) {
            return alarms.get(position);
        }

        @Override
        public View getView(final int position, final View v, final ViewGroup parent) {
            final Alarm a = getAlarm(position);
            final View view = layoutInflater.inflate(a.getAgency().getAlarmListItemViewId(), parent, false);

            if (a.isEnabled()) {
                final ImageView clock = (ImageView) view.findViewById(R.id.alarm_clock);
                clock.setImageBitmap(enabledClockBmp);

                final ImageView icon = (ImageView) view.findViewById(R.id.alarm_icon);
                icon.setImageBitmap(enabledIndicatorBmp);
            }

            Android.cptxt(view, R.id.alarm_time, a.getTimeStr());
            Android.cptxt(view, R.id.alarm_repeat, a.getRepeatStr());
            Android.cptxt(view, R.id.alarm_station, a.getStopName());
            Android.cptxt(view, R.id.alarm_label, a.getLabel());
            Android.cproute(view, R.id.alarm_line, a.getRoute());

            return view;
        }
    }

    @Override
    public final void onCreate(final Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setDefaultKeyMode(DEFAULT_KEYS_SHORTCUT);

        // If no data was given in the intent (because we were started
        // as a MAIN activity), then use our default content provider.
        final Intent intent = getIntent();

        if (intent.getData() == null) {
            intent.setData(Alarms.CONTENT_URI);
        }

        setContentView(R.layout.all);

        allAllarms = (ListView) findViewById(R.id.all_alarms);
        allAllarms.setOnCreateContextMenuListener(this);
        allAllarms.setOnItemClickListener(this);

        final View v = findViewById(R.id.add_alarm);
        v.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(final View v) {
                    selectNewAlarmType();
                }
            });
    }

    @Override
    protected void onResume() {
        super.onResume();

        layoutInflater = (LayoutInflater) this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        enabledClockBmp = BitmapFactory.decodeResource(getResources(), R.drawable.ic_clock_alarm_on);
        enabledIndicatorBmp = BitmapFactory.decodeResource(getResources(), R.drawable.ic_indicator_on);

        updateAllAlarmsAdapter();

        //
        loadingDialog = new ProgressDialog(this);
        loadingDialog.setMessage(getText(R.string.loading));
        loadingDialog.setIndeterminate(true);
        loadingDialog.setCancelable(true);
    }

    private void updateAllAlarmsAdapter() {
        //XXX n/s if we need ot reset adapter each time or if we can 'refresh' adapter itself.
        // With a managed query. The Activity will handle closing and requerying the cursor
        // when needed.  - But, managed seems flaky and is deprecated in more recent version of andriod.
        final Cursor cursor = managedQuery(getIntent().getData(), Projections.AlarmsAll.PROJECTION, null, null, Alarms.DEFAULT_SORT_ORDER);

        final AlarmAdapter adapter = new AlarmAdapter(this, cursor);
        allAllarms.setAdapter(adapter);
    }

    @Override
    public final boolean onCreateOptionsMenu(final Menu menu) {
        super.onCreateOptionsMenu(menu);

        menu.add(0, MENU_ITEM_INSERT, 0, R.string.add_alarm).setShortcut('3', 'a').setIcon(android.R.drawable.ic_menu_add);
        menu.add(0, MENU_ITEM_ABOUT, 1, R.string.about).setShortcut('6', 'i').setIcon(android.R.drawable.ic_menu_info_details);
        menu.add(0, MENU_ITEM_SETTING, 2, R.string.settings).setShortcut('9', 's').setIcon(android.R.drawable.ic_menu_preferences);

        return true;
    }

    @Override
    public final boolean onOptionsItemSelected(final MenuItem item) {
        switch (item.getItemId()) {
            case MENU_ITEM_INSERT:
                selectNewAlarmType();

                return true;

            case MENU_ITEM_SETTING:
                startActivity(new Intent(Constants.ACTION_SETTINGS));

                return true;

            case MENU_ITEM_ABOUT:
                startActivity(new Intent(Constants.ACTION_ABOUT));

                return true;

            default:
                return super.onOptionsItemSelected(item);
        }
    }

    private void selectNewAlarmType() {
        final AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setTitle(R.string.add_alarm);

        final CharSequence[] items = new CharSequence[] {
                                                            getText(R.string.agency_wmata_train),
                                                            getText(R.string.agency_wmata_bus)
        };
        builder.setSingleChoiceItems(items, 0, new DialogInterface.OnClickListener() {
                @Override
                public void onClick(final DialogInterface dialog, final int id) {
                    dialog.dismiss();

                    if (id == 0) {
                        gotoInsert(TrainAgency.WMATA_TRAIN_AGENCY_ID);
                    } else {
                        gotoInsert(BusAgency.WMATA_BUS_AGENCY_ID);
                    }
                }
            });

        builder.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
                @Override
                public void onClick(final DialogInterface dialog, final int id) {
                    dialog.dismiss();
                }
            });
        builder.show();
    }

    private void gotoInsert(final int agencyId) {
        loadingDialog.show();
        App.getAgency(agencyId, this).gotoInsert(getIntent().getData());
    }

    @Override
    public final void onCreateContextMenu(final ContextMenu menu, final View view, final ContextMenuInfo menuInfo) {
        AdapterView.AdapterContextMenuInfo info;

        try {
            info = (AdapterView.AdapterContextMenuInfo) menuInfo;
        } catch (final ClassCastException e) {
            Log.e(TAG, "bad menuInfo", e);

            return;
        }

        final Alarm a = (Alarm) allAllarms.getAdapter().getItem(info.position);

        if (a == null) {
            // For some reason the requested item isn't available, do nothing
            return;
        }

        menu.setHeaderTitle(a.getLabelOrStopName());
        menu.add(0, MENU_ITEM_VIEW, 0, R.string.view_alarm);
        menu.add(0, MENU_ITEM_START_NOW, 0, R.string.run);
        /* XXX uncomment once figure out how to refresh listview.
        if(a.isEnabled()) {
        menu.add(0, MENU_ITEM_DISABLE, 0, R.string.alarm_disable);
        } else {
        menu.add(0, MENU_ITEM_ENABLE, 0, R.string.alarm_enable);
        }
         */
        menu.add(0, MENU_ITEM_EDIT, 0, R.string.edit);
        menu.add(0, MENU_ITEM_DELETE, 0, R.string.delete);
    }

    @Override
    public final boolean onContextItemSelected(final MenuItem item) {
        AdapterView.AdapterContextMenuInfo info;

        try {
            info = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
        } catch (final ClassCastException e) {
            Log.e(TAG, "bad menuInfo", e);

            return false;
        }

        final Uri alarmUri = ContentUris.withAppendedId(getIntent().getData(), info.id);
        final Alarm a = App.loadAlarm(alarmUri, this);

        switch (item.getItemId()) {
            case MENU_ITEM_START_NOW:
                return a.startPollingNow();

            case MENU_ITEM_EDIT:
                loadingDialog.show();

                return a.gotoEdit();

            case MENU_ITEM_DELETE: {
                final AlertDialog.Builder builder = new AlertDialog.Builder(this);
                builder.setMessage(R.string.confirm_delete_alarm).setTitle(R.string.delete_alarm).setCancelable(false).setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(final DialogInterface dialog, final int id) {
                            a.delete();
                            updateAllAlarmsAdapter();
                            dialog.dismiss();
                        }
                    }).setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(final DialogInterface dialog, final int id) {
                            dialog.dismiss();
                        }
                    });
                builder.show();

                return true;
            }

            case MENU_ITEM_VIEW:
                loadingDialog.show();

                return a.gotoView();

            case MENU_ITEM_ENABLE: {
                a.setEnabled(true);
                updateAllAlarmsAdapter();

                return a.update();
            }

            case MENU_ITEM_DISABLE: {
                a.setEnabled(false);
                updateAllAlarmsAdapter();

                return a.update();
            }

            default:
                return false;
        }
    }

    @Override
    public final void onItemClick(final AdapterView<?> l, final View v, final int position, final long id) {
        final Alarm a = (Alarm) l.getAdapter().getItem(position);

        final String action = getIntent().getAction();

        if (Intent.ACTION_PICK.equals(action) || Intent.ACTION_GET_CONTENT.equals(action)) {
            setResult(RESULT_OK, new Intent().setData(a.getUri()));
        } else {
            loadingDialog.show();
            a.gotoEdit();

//            super.openContextMenu(v);//XXX Add preference.defaultClickAction() and tie that back to 
        }
    }

    @Override
    protected void onStop() {
        super.onStop();

        if (loadingDialog != null) {
            loadingDialog.hide();
        }
    }
}
